package cn.bonoon.kernel.io.synchronize;

import java.io.File;
import java.util.Collections;
import java.util.List;

import cn.bonoon.kernel.io.AbstractTaskThread;

/**
 * 这里还没有对多服务器的同步进行处理，所以配置时只能启动一个服务器，否则会出现同步问题；
 * 这里也支持本地的同步，如使用移动硬盘等情况
 * 
 * @author jackson
 *
 */
public abstract class AbstractFileSynchronizeTask extends AbstractTaskThread<File>{

	protected String encoding = "UTF-8";
	
	
	/** 需要被同步的目录 */
	private File root;
	
	protected int rootPathLength;

	/** 设置不需要被同步的目录 */
	private List<String> excludeDirecorties = Collections.emptyList();
	
	/** 需要被同步的地方的根目录，可以不指定；
	 * 如：硬盘指定为(F://files/backup)；
	 * FTP服务器指定为"backup"，这个目录是指用户登录后重新指定的目录，如果使用的是用户登录时默认的目录，则为null； **/
	protected String targetRootPath = null;
	
	public AbstractFileSynchronizeTask(){
		super(true, true);
	}
	
	/** 一定要被调用的 */
	public void init(File root){
		this.root = root;
		this.rootPathLength = root.getPath().length();
	}
	
	@Override
	protected boolean starting() {
		if(null == root){
			log.error("同步任务未初始化，无法被执行！");
			return false;
		}

		//设置需要处理的根目录
		needSynchronizeItems.add(root);
		
		return true;
	}
	
	/** 执行一个文件的同步任务 */
	protected abstract void internalExecute(File localFile) throws Exception;
	
	@Override
	protected boolean executeTask(File task) throws Exception {
		add(task.listFiles());
		
		/*
		 * 开始执行文件同步的任务
		 * 这里执行的时间可能会比较长，所以这里需要判断如果当前已经停止了，则要退出子线程任务
		 */
		for(File file : task.listFiles()){
			
			//外部线程请求任务中断
			if(!running) break;
			
			if(file.isFile()){
				internalExecute(file);
			}
		}
		
		return true;
	}
	
	@Override
	protected boolean checked(File item) {
		return item.isDirectory() && !isExclude(item);
	}
	
	/** 判断一个目录是否被排除，不对他进行传输的 */
	private boolean isExclude(File dir){
		String sp = dir.getPath();
		for(String t : excludeDirecorties){
			if(sp.endsWith(t)) return true;
		}
		return false;
	}
	
	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
	
	public void setExcludeDirecorties(List<String> excludeDirecorties) {
		this.excludeDirecorties = excludeDirecorties;
	}
	
	public void setTargetRootPath(String targetRootPath) {
		this.targetRootPath = targetRootPath;
	}
	
}
